/**
 * 极区方位投影坐标转换工具函数
 * 用于处理极区地图的屏幕坐标与经纬度坐标之间的转换
 */

/**
 * 将屏幕坐标转换为极区经纬度坐标
 * @param screenX 屏幕X坐标
 * @param screenY 屏幕Y坐标
 * @param canvasWidth 画布宽度
 * @param canvasHeight 画布高度
 * @param panX 平移X偏移
 * @param panY 平移Y偏移
 * @param scale 缩放比例
 * @param polarType 极区类型（north/south）
 * @returns 经纬度坐标 {lat, lng} 或 null（如果超出极区范围）
 */
export function screenToLatLng(
  screenX: number,
  screenY: number,
  canvasWidth: number,
  canvasHeight: number,
  panX: number,
  panY: number,
  scale: number,
  polarType: "north" | "south"
): { lat: number; lng: number } | null {
  // 计算画布中心
  const centerX = canvasWidth / 2;
  const centerY = canvasHeight / 2;
  
  // 计算极区地图的半径
  const maxRadius = Math.min(canvasWidth, canvasHeight) / 2 - 20;
  
  // 将屏幕坐标转换为相对于地图中心的坐标
  const relativeX = (screenX - centerX - panX) / scale;
  const relativeY = (screenY - centerY - panY) / scale;
  
  // 计算距离中心的距离
  const distance = Math.sqrt(relativeX * relativeX + relativeY * relativeY);
  
  // 检查是否在极区圆形范围内
  if (distance > maxRadius) {
    return null;
  }
  
  // 计算角度（弧度）
  // 调整角度计算，使0度经度指向正下方（6点钟方向）
  let angle = Math.atan2(relativeX, relativeY);
  
  // 对于南极，需要调整角度计算
  if (polarType === "south") {
    angle = -angle + Math.PI;
  }
  
  // 转换为经度（-180到180度）
  let lng = (angle * 180) / Math.PI;
  
  // 确保经度在-180到180度范围内
  while (lng > 180) lng -= 360;
  while (lng < -180) lng += 360;
  
  // 计算纬度（60度到90度）
  // 在极区方位投影中，使用等距方位投影公式
  const latRange = 30; // 90 - 60 = 30度
  const normalizedDistance = distance / maxRadius;
  
  // 使用更精确的投影公式
  // 对于等距方位投影，距离与余纬角成正比
  const colatitude = (normalizedDistance * latRange * Math.PI) / 180;
  const lat = 90 - (colatitude * 180) / Math.PI;
  
  // 根据极区类型调整纬度
  // 对于南极，我们需要将计算出的纬度转换为负值
  const finalLat = polarType === "north" ? lat : -lat;
  
  // 确保纬度在有效范围内
  if (polarType === "north" && (finalLat < 60 || finalLat > 90)) {
    return null;
  }
  if (polarType === "south" && (finalLat < -90 || finalLat > -60)) {
    return null;
  }
  
  return { lat: finalLat, lng };
}

/**
 * 将经纬度坐标转换为屏幕坐标
 * @param lat 纬度
 * @param lng 经度
 * @param canvasWidth 画布宽度
 * @param canvasHeight 画布高度
 * @param panX 平移X偏移
 * @param panY 平移Y偏移
 * @param scale 缩放比例
 * @param polarType 极区类型（north/south）
 * @returns 屏幕坐标 {x, y} 或 null（如果超出极区范围）
 */
export function latLngToScreen(
  lat: number,
  lng: number,
  canvasWidth: number,
  canvasHeight: number,
  panX: number,
  panY: number,
  scale: number,
  polarType: "north" | "south"
): { x: number; y: number } | null {
  // 检查纬度是否在极区范围内
  if (polarType === "north" && (lat < 60 || lat > 90)) {
    return null;
  }
  if (polarType === "south" && (lat < -90 || lat > -60)) {
    return null;
  }
  
  // 计算画布中心
  const centerX = canvasWidth / 2;
  const centerY = canvasHeight / 2;
  
  // 计算极区地图的半径
  const maxRadius = Math.min(canvasWidth, canvasHeight) / 2 - 20;
  
  // 计算距离中心的距离
  const latRange = 30; // 90 - 60 = 30度
  // 对于南极，我们需要使用绝对值的纬度来计算距离
  const normalizedLat = polarType === "north" ? lat : Math.abs(lat);
  
  // 使用更精确的投影公式
  // 对于等距方位投影，余纬角与距离成正比
  const colatitude = ((90 - normalizedLat) * Math.PI) / 180;
  const normalizedDistance = (colatitude * 180) / (latRange * Math.PI);
  const distance = normalizedDistance * maxRadius;
  
  // 确保经度在-180到180度范围内
  let normalizedLng = lng;
  while (normalizedLng > 180) normalizedLng -= 360;
  while (normalizedLng < -180) normalizedLng += 360;
  
  // 计算角度（弧度）
  // 调整角度计算，使0度经度指向正下方（6点钟方向）
  const angle = (normalizedLng * Math.PI) / 180;
  
  // 计算相对于地图中心的坐标
  // 调整坐标计算，使0度经度指向正下方
  // 对于北极，需要调整坐标计算方向
  const relativeX = distance * Math.sin(angle);
  let relativeY = distance * Math.cos(angle);
  
  // 对于南极，需要Y轴翻转
  if (polarType === "south") {
    relativeY = -relativeY;
  }
  
  // 转换为屏幕坐标
  const screenX = centerX + panX + relativeX * scale;
  const screenY = centerY + panY + relativeY * scale;
  
  return { x: screenX, y: screenY };
}

/**
 * 检查坐标是否在极区范围内
 * @param lat 纬度
 * @param lng 经度
 * @param polarType 极区类型
 * @returns 是否在范围内
 */
export function isInPolarRange(lat: number, lng: number, polarType: "north" | "south"): boolean {
  if (polarType === "north") {
    return lat >= 60 && lat <= 90;
  } else {
    return lat >= -90 && lat <= -60;
  }
}

/**
 * 格式化坐标显示
 * @param lat 纬度
 * @param lng 经度
 * @returns 格式化后的坐标字符串
 */
export function formatCoordinate(lat: number, lng: number): string {
  return `${lat.toFixed(4)}°, ${lng.toFixed(4)}°`;
}

/**
 * 极区方位投影工具类
 * 提供静态方法进行坐标转换
 */
export class PolarProjectionUtils {
  static screenToLatLng = screenToLatLng;
  static latLngToScreen = latLngToScreen;
  static isInPolarRange = isInPolarRange;
  static formatCoordinate = formatCoordinate;
}
